package uk.ac.glasgow.demosocs.electionstore;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import uk.ac.glasgow.demosocs.Election;
import uk.ac.glasgow.demosocs.impl.ElectionImpl;

/** 
 * A simple file based implementation of a store for users. 
 */
public class ElectionStoreImpl implements ElectionStore {
	private Map<String,ElectionImpl> elections;
	private File storeFile;
	
	/**
	 * Constructs a new store in the specified file location.
	 * @param fileName
	 */
	@SuppressWarnings("unchecked")
	public ElectionStoreImpl(String fileName){
		storeFile = new File(fileName);
		if (storeFile.exists()){
			try {
				ObjectInputStream ois = 
					new ObjectInputStream(new FileInputStream(storeFile));
				elections = (Map<String,ElectionImpl>) ois.readObject();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		else
			this.elections = new HashMap<String,ElectionImpl>();
	}
	
	/**
	 * Adds a new election to the data store
	 * @param id an identifier for the election
	 * @param type the type id for the election
	 */
	public void addElection(String id, String type) {
		ElectionImpl election = new ElectionImpl(id,type);
		elections.put(id,election);
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(storeFile));
			oos.writeObject(elections);
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void storeElection(String id, ElectionImpl election) {
		elections.put(id,election);
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(storeFile));
			oos.writeObject(elections);
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Gets an election from the data store
	 * @param electionId an identifier for the election
	 */
	public ElectionImpl getElection(String electionId) {
		ElectionImpl election = elections.get(electionId);
		return election;
	}
	
	/**
	 * Edits an election
	 * @param electionId the ID of the election
	 * @param openNominations the date to open nominations for the election
	 * @param start the date to open the election for voting
	 * @param end the date to close the election
	 * @param electoratelectionID the electorate that can vote in the election
	 */
	public void editElection(String electionId, Date openNominations, Date start, Date end, String electoratelectionID) {
		ElectionImpl election = elections.get(electionId);
		election.setOpenNominations(openNominations);
		election.setStart(start);
		election.setEnd(end);
		election.setElectorateId(electoratelectionID);
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(storeFile));
			oos.writeObject(elections);
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Returns all elections in the data store
	 * @return A set of all elections
	 */
	public Set<Election> getElections() {
		HashSet<Election> electionSet = new HashSet<Election>();
		for(Map.Entry<String, ElectionImpl> e : elections.entrySet()) {
			electionSet.add((Election) e.getValue());
		}
		return electionSet;
	}
}
